home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / glass / glass.lha / GLASS / libcvr / symbol.c < prev    next >
C/C++ Source or Header  |  1990-11-09  |  4KB  |  174 lines

  1. /* File: symbol.c
  2.  
  3.    Symbol table manager.
  4.  */
  5.  
  6. #include "all.h"
  7. #include "cvr.h"
  8.  
  9. static int gensymworking;
  10. static long int gensymnum;
  11.  
  12. /* This is the table of symbol strings. Each used symbol string should
  13.    occur here exactly once, so that a compare on equal names is
  14.    simplified to comparing the pointers to the strings. This must be
  15.    ensured by the routines 'addsymbol()' and 'gensymbol()'.
  16.  */
  17. static symbol symtab[HASHWIDTH];
  18.  
  19. /* The hashing function:
  20.    Return a value in the range 0..HASHWIDTH-1.
  21.  
  22.    Current hashing function:
  23.    Add all characters in the given string and shift one position
  24.    after each addition.
  25.  */
  26. static unsigned int hash( s )
  27.  register char *s;
  28. {
  29.     register unsigned int sum = 0;
  30.  
  31.     while( *s != '\0' ){
  32.     sum += *s++;
  33.     sum <<= 1;
  34.     }
  35.     return( sum % HASHWIDTH );
  36. }
  37.  
  38. /* make a new storage space for a symbol */
  39. static symbol newsymbol( l, s )
  40.  symbol l;
  41.  char *s;
  42. {
  43.     register symbol new;
  44.  
  45.     new = (symbol) ckmalloc( (unsigned int) sizeof(*new) );
  46.     new->next = l;
  47.     new->symstr = s;
  48.     new->priority = 2;
  49.     return( new );
  50. }
  51.  
  52. /* Try to locate string 'name' in the given list 'list'.
  53.  
  54.    If the name occurs in the list, a pointer to the entry is returned,
  55.    else symbolNIL is returned.
  56.  */
  57. static symbol dofindsymbol( name, list )
  58.  register char *name;
  59.  register symbol list;
  60. {
  61.  
  62.     while( list != symbolNIL ){
  63.     if( strcmp( list->symstr, name ) == 0 ) return( list );
  64.     list = list->next;
  65.     }
  66.     return( symbolNIL );
  67. }
  68.  
  69. /* Search the symbol table for the given symbol.
  70.    If the name occurs in the table, a pointer to the entry is returned,
  71.    else symbolNIL is returned.
  72.  */
  73. symbol findsymbol( name )
  74.  register char *name;
  75. {
  76.     register symbol entry;
  77.     unsigned int hashval;
  78.  
  79.     hashval = hash( name );
  80.     entry = dofindsymbol( name, symtab[hashval] );
  81.     return( entry );
  82. }
  83.  
  84. /* Add string 'name' to the symbol table.
  85.    If the name already occurs in the table, a pointer to the old
  86.    entry is returned, else a new entry is added, and a pointer to this
  87.    new entry is returned.
  88.  
  89.    This routine must ensure that for all symbols with the same name,
  90.    the same pointer is returned.
  91.  */
  92. symbol addsymbol( name )
  93.  register char *name;
  94. {
  95.     register symbol entry;
  96.     unsigned int hashval;
  97.  
  98.     if( gensymworking ){
  99.     fprintf(
  100.         stderr,
  101.         "You can't add symbols after using gensymbol() (name = '%s')\n",
  102.         name
  103.     );
  104.     exit( 1 );
  105.     }
  106.     hashval = hash( name );
  107.     entry = dofindsymbol( name, symtab[hashval] );
  108.     if( entry != symbolNIL ) return( entry );
  109.     entry = newsymbol( symtab[hashval], new_string( name ) );
  110.     symtab[hashval] = entry;
  111.     return( entry );
  112. }
  113.  
  114. /* given a prefix 'pre', generate a new symbol with an unique name.
  115.  
  116.    This is done by systematically generating names of the form
  117.    <pre><number> until a name is found that doesn't occur in the
  118.    list.
  119.  
  120.    To ensure that the symbol remains unique, the flag 'gensymworking'
  121.    is set after the first symbol has been generated.  After that it is
  122.    an error to add new symbols to the table using 'addsymbol()'.
  123.  */
  124. symbol gensymbol( pre )
  125.  char *pre;
  126. {
  127.     unsigned int hashval;
  128.     register char *name;
  129.     register symbol entry;
  130.  
  131.     name = new_string( pre );
  132.     name = ckrealloc( name, (unsigned int) strlen( pre ) + 30 );
  133.     for(;;){
  134.     (void) sprintf( name, "%s%ld", pre, gensymnum++ );
  135.     hashval = hash( name );
  136.     if( dofindsymbol( name, symtab[hashval] ) == symbolNIL ) break;
  137.     }
  138.     entry = newsymbol( symtab[hashval], name );
  139.     entry->priority = 0;
  140.     symtab[hashval] = entry;
  141.     return( entry );
  142. }
  143.  
  144. /* initalize symbol routines */
  145. void initsymbol(){
  146.     register int i;
  147.  
  148.     for( i=0; i<HASHWIDTH; i++ ){
  149.     symtab[i] = symbolNIL;
  150.     }
  151.     gensymworking = FALSE;
  152.     gensymnum = 0;
  153. }
  154.  
  155. /* flush symbol routines */
  156. void flushsymbol(){
  157.     symbol s;
  158.     symbol n;
  159.     register int i;
  160.  
  161.     for( i=0; i<HASHWIDTH; i++ ){
  162.     s = symtab[i];
  163.     while( s != symbolNIL ){
  164.         n = s->next;
  165.         free( s->symstr );
  166.         free( (char *) s );
  167.         s = n;
  168.     }
  169.     symtab[i] = symbolNIL;
  170.     }
  171.     gensymworking = FALSE;
  172.     gensymnum = 0;
  173. }
  174.